#include <Arduino.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <WebServer_ESP32_SC_W5500.h>
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <Time.h>
#if !( defined(ESP32) )
  #error This code is designed for (SP32_S2/3 + W5500) to run on ESP32 platform! Please check your Tools->Board setting.
#endif

// 串口配置
#define EXT_UART_TX 43
#define EXT_UART_RX 44
//NFC模块的中断监听的GPIO
#define INT_PIN 33
HardwareSerial ExtSerial(1); // 使用UART1
// 必须将INT连接到GPIOxx的ping上，否则芯片不工作
#define INT_GPIO            10
#define MISO_GPIO           12
#define MOSI_GPIO           11
#define SCK_GPIO            13
#define CS_GPIO             14

// 全局变量
volatile bool dataReady = false;
String receivedData;
String preSendData;
uint32_t dataLength = 0;
// const char* serverURL = "http://192.168.1.120:8888/report/cmd";
// const char* debugLogUploadServerURL = "http://192.168.1.120:8888/report/debugLog";
const char* serverURL = "http://192.168.32.177:8888/report/cmd";
const char* debugLogUploadServerURL = "http://192.168.32.177:8888/report/debugLog";

void uploadDebugLogs(String log) {
  if(log.length() > 512){
    return;
  }
  HTTPClient http;
  String response = "";
  http.begin(debugLogUploadServerURL);
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  String postData = "log=" + log;
  int httpCode = http.POST(postData);
  if (httpCode == HTTP_CODE_OK) {
    response = http.getString();
    http.end();
  }
  http.end();
}

// MQTT配置
void callback(char* topic, byte* payload, unsigned int length)
{
  uploadDebugLogs("Message arrived [");
  uploadDebugLogs(topic);
  uploadDebugLogs("length: " + String(length));
  uploadDebugLogs("] ");
  preSendData="";
  dataLength=0;
  for (unsigned int i = 0; i < length; i++)
  {
    //Serial.print((char)payload[i]);
    preSendData += (char)payload[i];
  }
  preSendData += "END";
  // 直接获取字节长度
  dataLength = preSendData.length(); // 对于 ASCII 字符，暂时这样计算
  // 如果需要处理多字节字符，使用以下方式
  // byte buffer[preSendData.length() + 1];
  // dataLength = preSendData.getBytes(buffer, sizeof(buffer));
  uploadDebugLogs("dataLength: " + String(dataLength));
  uploadDebugLogs(preSendData);
  processSendProtocol();
}
// const char* mqttServer = "192.168.1.120";   
// const int mqttPort = 1883; 
const char* mqttServer = "192.168.32.69";   
const int mqttPort = 1883; 
const char *TOPIC     = "nfc_server/1";               // 要发布数据的主体
const char *subTopic  = "nfc_server/2";               // 要订阅数据的主题
const char *mqtt_username = "obs";
const char *mqtt_psd = "1q2w3e4r5t,./";
WiFiClient    ethClient;
PubSubClient    client(mqttServer, mqttPort, callback, ethClient);
#define MQTT_PUBLISH_INTERVAL_MS       10000L
// unsigned long currentMillis = millis();

String data         = "Hello from MQTTClient_Basic on " + String(ARDUINO_BOARD) + " with " + String(SHIELD_TYPE);
const char *pubData = data.c_str();

unsigned long lastMsg = 0;
unsigned long previousMillis=0;

// 协议参数
const byte HEADER[] = {0xFE, 0xFE, 0xFE, 0xFE};
const byte CHECK_REQ[] = {0xFE, 0xFE, 0xFE, 0xFE, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0x45, 0x4E, 0x44};
const byte SUCCESS_RESPONSE[] = {0xFE, 0xFE, 0xFE, 0xFE, 0x04, 0x00, 0x00, 0x00, 0x14, 0xE7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x45, 0x4E, 0x44};
const byte BUSY_RESPONSE[] = {0xFE, 0xFE, 0xFE, 0xFE, 0x04, 0x00, 0x00, 0x00, 0x14, 0xE9, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x45, 0x4E, 0x44};

// 继电器配置（低电平有效）
const int relayPin = 20;    // 实际连接的GPIO引脚
bool relayStatus = false;  // 状态变量（true=开启）

WebServer server(9999);
#define NUMBER_OF_MAC      20
byte mac[][NUMBER_OF_MAC] =
{
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x01 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x02 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x03 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x04 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x05 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x06 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x07 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x08 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x09 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0A },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0B },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0C },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0D },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x0E },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x0F },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x10 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x11 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x12 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x13 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0xBE, 0x14 },
};

// 本地IP信息的配置，这里的配置默认不启用（默认使用本地DHCP获取地址），要启用就需要放开下面代码中的//ETH.config(myIP, myGW, mySN, myDNS);
// IPAddress myIP(192, 168, 1, 232);
// IPAddress myGW(192, 168, 1, 1);
IPAddress myIP(192, 168, 32, 232);
IPAddress myGW(192, 168, 32, 1);
IPAddress mySN(255, 255, 255, 0);
IPAddress myDNS(8, 8, 8, 8);



//设置中断的状态
void IRAM_ATTR extInterrupt() {
  dataReady = true;
}

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  ExtSerial.begin(115200, SERIAL_8N1, EXT_UART_RX, EXT_UART_TX);
  Serial.println("Begin executing...");
  //while (!Serial && (millis() < 5000));
 
  // 初始化继电器控制引脚
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH);  // 初始设置为高电平（关闭继电器）
  relayStatus = false;          // 初始状态为关闭

  ET_LOGWARN(F("Default SPI pinout:"));
  ET_LOGWARN1(F("SPI_HOST:"), ETH_SPI_HOST);
  ET_LOGWARN1(F("MOSI:"), MOSI_GPIO);
  ET_LOGWARN1(F("MISO:"), MISO_GPIO);
  ET_LOGWARN1(F("SCK:"),  SCK_GPIO);
  ET_LOGWARN1(F("CS:"),   CS_GPIO);
  ET_LOGWARN1(F("INT:"),  INT_GPIO);
  ET_LOGWARN1(F("SPI Clock (MHz):"), SPI_CLOCK_MHZ);
  ET_LOGWARN(F("========================="));

  ESP32_W5500_onEvent();
  uint16_t index = millis() % NUMBER_OF_MAC;
  ETH.begin( MISO_GPIO, MOSI_GPIO, SCK_GPIO, CS_GPIO, INT_GPIO, SPI_CLOCK_MHZ, ETH_SPI_HOST, mac[index] );
  //配置w5500网卡静态地址，这句很重要
  ETH.config(myIP, myGW, mySN, myDNS);
  ESP32_W5500_waitForConnect();
  delay(1500);
  // 设置路由处理
  server.on("/manage/status", HTTP_GET, handleStatus);    // GET请求处理
  server.on("/manage/control", HTTP_POST, handleControl); // POST请求处理
  server.onNotFound(handleNotFound);                      // 未定义路由处理

  server.begin();
  Serial.print("Server started at ");
  Serial.println(ETH.localIP());
  //uploadDebugLogs("Server started at " + ETH.localIP());
   //设置中断监听引脚为上拉
  pinMode(INT_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(INT_PIN), extInterrupt, RISING);

  uploadDebugLogs("注册mqtt服务");
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);
  client.setBufferSize(16382);
  
}

// 打印MQTT客户端状态
void printClientState(int state) {
  switch (state) {
    case MQTT_CONNECTED:
      uploadDebugLogs("MQTT已连接");
      break;
    case MQTT_DISCONNECTED:
      uploadDebugLogs("MQTT已断开连接");
      break;
  }
}
void loop() {
  server.handleClient();
  if (dataReady) {
    dataReady = false;
    readSerialData();
    uploadDebugLogs("loop readSerialData");
    uploadDebugLogs(receivedData);
    if(receivedData != "44" && receivedData != ""){
      sendMQTTMsg(receivedData.c_str());
      String httpResponse;
      // if (sendHTTPRequest(receivedData, httpResponse)) {
      //   int status;
      //   String responseData;
        
      //   if (parseJSONResponse(httpResponse, status, responseData)) {
      //     if (status == 99) {
      //       preSendData = responseData;
      //       dataLength = preSendData.length();
      //       processSendProtocol();
      //     }
      //   }
      // }
    }
    dataReady=false;
  }
    
  static unsigned long now;
  unsigned long currentMillis = millis();
  if (!client.connected() && (currentMillis - previousMillis >= 5000)) {
    previousMillis = currentMillis;
    uploadDebugLogs("mqtt未连接,启动重连机制");
    reconnect();
  }else if (currentMillis - previousMillis >= 80000) {
    previousMillis = currentMillis;
    uploadDebugLogs("mqtt强制重连");
    client.disconnect();
    reconnect();
  }
  // 处理MQTT网络事件，这是接收订阅消息的关键
  if (client.connected()) {
    client.loop();  // 添加这一行处理MQTT网络事件
  }
  int clientState = client.state();
  switch (clientState) {
    case MQTT_CONNECTED:
      //uploadDebugLogs("STATUS:MQTT connected");
      break;
    case MQTT_CONNECT_BAD_PROTOCOL:
      uploadDebugLogs("STATUS:MQTT connection error: Bad protocol");
      break;
    case MQTT_CONNECT_BAD_CLIENT_ID:
      uploadDebugLogs("STATUS:MQTT connection error: Bad client ID");
      break;
    case MQTT_CONNECT_UNAVAILABLE:
      uploadDebugLogs("STATUS:MQTT connection error: Server unavailable");
      break;
    case MQTT_CONNECT_BAD_CREDENTIALS:
      uploadDebugLogs("STATUS:MQTT connection error: Bad credentials");
      break;
    case MQTT_CONNECT_UNAUTHORIZED:
      uploadDebugLogs("STATUS:MQTT connection error: Unauthorized");
      break;
    default:
      uploadDebugLogs("STATUS:MQTT connection state: " + String(clientState));
  }
  // now = millis();
  // if(client.connected()){
  //   if (now - lastMsg > MQTT_PUBLISH_INTERVAL_MS)
  //   {
  //     lastMsg = now;
  //     char timestampBuffer[11]; // 用于存储时间戳字符串，最多10位数字 + 结束符 '\0'
  //     // 获取当前时间戳（从系统启动开始的毫秒数转换为秒数）
  //     unsigned long timestamp = millis() / 1000;
      
  //     // 将时间戳转换为字符串并赋值给_pubdata
  //     sprintf(timestampBuffer, "%lu", timestamp);
  //     char *_pubdata = timestampBuffer;
  //     if (!client.publish(TOPIC, _pubdata))
  //     {
  //       uploadDebugLogs("MQTT Message failed to send.");
  //     }else{
  //       uploadDebugLogs("MQTT Message Send : " + String(TOPIC) + " => ");
  //       uploadDebugLogs(_pubdata);
  //       int clientState = client.state();
  //       printClientState(clientState);
  //       if (currentMillis - previousMillis >= 20000) {
  //         previousMillis = currentMillis;
  //         uploadDebugLogs("mqtt强制重连");
  //         client.disconnect();
  //         reconnect();
  //       }
  //     }
  //   }
  // }else{
  //   uploadDebugLogs("发送消息前发现mqtt未连接,启动重连机制");
  //   reconnect();
  // }
  
}

void sendMQTTMsg(const char *_pubdata){
  if(client.connected()){
      if (!client.publish(TOPIC, _pubdata))
      {
        uploadDebugLogs("MQTT Message failed to send.");
      }else{
        uploadDebugLogs("MQTT Message Send : " + String(TOPIC) + " => ");
        uploadDebugLogs(_pubdata);
      }
    
  }else{
    uploadDebugLogs("发送消息前发现mqtt未连接,启动重连机制");
    reconnect();
    sendMQTTMsg(_pubdata);
  }
}

// 处理状态请求
void handleStatus() {
  // 增加操作间隔保护
  static unsigned long lastOperation = 0;
  if (millis() - lastOperation < 1000) { // 1秒操作间隔
    server.send(429, "text/plain", "操作过于频繁");
    return;
  }
  lastOperation = millis();
  String response = "{\"status\":1}";
  server.send(200, "application/json", response);
}

// 处理控制请求
void handleControl() {
  // 增加操作间隔保护
  static unsigned long lastOperation = 0;
  if (millis() - lastOperation < 1000) { // 1秒操作间隔
    server.send(429, "text/plain", "操作过于频繁");
    return;
  }
  lastOperation = millis();
  if (!server.hasArg("status")) {
    server.send(400, "application/json", "{\"error\":\"Missing status parameter\"}");
    return;
  }

  String statusValue = server.arg("status");
  if (statusValue != "0" && statusValue != "1") {
    server.send(400, "application/json", "{\"error\":\"Invalid status value\"}");
    return;
  }

  // 低电平触发逻辑
  bool targetStatus = (statusValue == "1");
  digitalWrite(relayPin, targetStatus ? LOW : HIGH);  // 开启时输出LOW
  relayStatus = targetStatus;  // 更新状态变量
  server.send(200, "application/json", "{\"success\":true, \"status\":" + String(relayStatus) + "}");
}

// 处理未定义路由
void handleNotFound() {
  server.send(404, "text/plain", "Not Found");
}
//备用 转换为普通字符串
void readSerialDataToAscii() {
 receivedData="";
  while (ExtSerial.available()) {
    char c = ExtSerial.read();
    receivedData += c;
  }
}

void readSerialData() {
  receivedData = "";
  receivedData.reserve(ExtSerial.available() * 2); // 预分配内存
  while (ExtSerial.available()) {
    byte b = ExtSerial.read();
    // 手动转换提升效率
    receivedData += "0123456789ABCDEF"[b >> 4];
    receivedData += "0123456789ABCDEF"[b & 0x0F];
  }
}
//备用 转换为hex字符串
void readSerialDataToHexStr() {
  receivedData = "";
  receivedData.reserve(ExtSerial.available() * 2); // 预分配内存
  while (ExtSerial.available()) {
    byte b = ExtSerial.read();
    // 手动转换提升效率
    receivedData += "0123456789ABCDEF"[b >> 4];
    receivedData += "0123456789ABCDEF"[b & 0x0F];
  }
}
bool sendHTTPRequest(String payload, String &response) {
  HTTPClient http;
  http.begin(serverURL);
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  
  String postData = "data=" + payload;
  int httpCode = http.POST(postData);
  
  if (httpCode == HTTP_CODE_OK) {
    response = http.getString();
    http.end();
    return true;
  }
  http.end();
  return false;
}

bool parseJSONResponse(String jsonStr, int &status, String &data) {
  DynamicJsonDocument doc(256);
  DeserializationError error = deserializeJson(doc, jsonStr);
  
  if (error) {
    Serial.print("JSON parse failed: ");
    Serial.println(error.c_str());
    status = doc["status"];
    data = jsonStr;
    return true;
  }
  
  status = doc["status"];
  data = doc["data"].as<String>();
  return true;
}

void prepareSendCommand(uint32_t length) {
  byte cmd[20];
  memcpy(cmd, HEADER, 4);
  cmd[4] = 0x02;
  memset(cmd+5, 0x00, 4);
  cmd[8] = 0x14;
  
  // 填充长度（大端序）
  cmd[9] = (length >> 24) & 0xFF;
  cmd[10] = (length >> 16) & 0xFF;
  cmd[11] = (length >> 8) & 0xFF;
  cmd[12] = length & 0xFF;
  
  memset(cmd+13, 0xFF, 4);
 // memset(cmd+14, 0xFF, 4);
  //memcpy(cmd+18, "END", 3);
  cmd[17]=0x45;
  cmd[18]=0x4E;
  cmd[19]=0x44;
  
  uploadDebugLogs("prepareSendCommand");
  ExtSerial.write(cmd, sizeof(cmd));
  // 转换为十六进制字符串
    char hex_str[41]; // 19字节*2 + 1个结束符
    const char hex_table[] = "0123456789ABCDEF";

    for (int i = 0; i < 20; i++) {
        unsigned char byte = cmd[i];
        hex_str[i*2]   = hex_table[byte >> 4];   // 高4位
        hex_str[i*2+1] = hex_table[byte & 0x0F]; // 低4位
    }
    hex_str[40] = '\0'; // 字符串结束符
  uploadDebugLogs(hex_str);
  // ExtSerial.write(CHECK_REQ,sizeof(CHECK_REQ));
}

bool checkResponse(const byte *expected, size_t len) {
  byte buffer[len];
  unsigned long start = millis();
  while (millis() - start < 500) {
    uploadDebugLogs("checkResponse while");
    if (ExtSerial.available() >= (int)len) {
      uploadDebugLogs("ExtSerial.available() >= (int)len");
      ExtSerial.readBytes(buffer, len);
      char hex_str[41];
      const char hex_table[] = "0123456789ABCDEF";
      for (int i = 0; i < len; i++) {
        unsigned char byte = buffer[i];
        hex_str[i*2]   = hex_table[byte >> 4];   // 高4位
        hex_str[i*2+1] = hex_table[byte & 0x0F]; // 低4位
    }
    hex_str[41] = '\0'; // 字符串结束符
    uploadDebugLogs(hex_str);
      int cp = memcmp(buffer, expected, len);
      bool rtn = cp == 0;
      uploadDebugLogs("memcmp(buffer, expected, len) == 0");
      char debug_buffer[128];

      sprintf(debug_buffer, "memcmp result:%d,return:%s", cp, rtn ? "true" : "false");

      uploadDebugLogs(debug_buffer);
      return rtn;
    }
  }
  return false;
}
void processSendProtocol() {
  uploadDebugLogs("Start sending data in chunks...");
  int retryCount = 0;
  const uint32_t CHUNK_SIZE = 512; // Maximum number of bytes per frame

  // Calculate the byte length directly
  uint32_t byteDataLength = preSendData.length(); // For ASCII characters, this is equivalent to the byte length
  byte buffer[byteDataLength + 1];
  preSendData.getBytes(buffer, sizeof(buffer));

  // Calculate the total number of frames
  int totalChunks = (byteDataLength + CHUNK_SIZE - 1) / CHUNK_SIZE;

  for (int chunk = 0; chunk < totalChunks; chunk++) {
    // Calculate the start position and length of the current frame
    uint32_t chunkStart = chunk * CHUNK_SIZE;
    int chunkLength = min(CHUNK_SIZE, byteDataLength - chunkStart);
    String chunkData = preSendData.substring(chunkStart, chunkStart + chunkLength);

    // Send the request command
    bool readyToSend = false;
    retryCount = 0;

    while (!readyToSend && retryCount < 4) {
      uploadDebugLogs("Sending request for chunk " + String(chunk + 1));
      prepareSendCommand(chunkLength);
      delay(5);
      if (checkResponse(SUCCESS_RESPONSE, sizeof(SUCCESS_RESPONSE))) {
        uploadDebugLogs("NFC device ready to receive chunk " + String(chunk + 1));
        readyToSend = true;
      } else if (checkResponse(BUSY_RESPONSE, sizeof(BUSY_RESPONSE))) {
        uploadDebugLogs("Device busy, retrying...");
        delay(100); // It is recommended to delay for more than 1 second (the manual recommends more than 750ms)
        retryCount++;
      } else {
        uploadDebugLogs("Invalid response, retrying...");
        delay(100);
        retryCount++;
      }
    }
    
    if (!readyToSend) {
      uploadDebugLogs("Failed to send chunk " + String(chunk + 1) + " after retries");
      return;
    }
    
    // 发送数据帧
    uploadDebugLogs("Sending chunk " + String(chunk + 1) + " of " + String(totalChunks));
    uploadDebugLogs(chunkData);
    ExtSerial.print(chunkData);
    delay(2200); // 短暂延迟确保数据发送完成
  }
  
  uploadDebugLogs("All chunks sent successfully");
}
// void processSendProtocol() {
//   uploadDebugLogs("Start return serial data....");
//   int retryCount = 0;
  
//   while (retryCount < 4) {
//     uploadDebugLogs("发送数据传输许可请求,数据长度:"+String(dataLength));
//     prepareSendCommand(dataLength);
//     uploadDebugLogs("processSendProtocol while");
//     if (checkResponse(SUCCESS_RESPONSE, sizeof(SUCCESS_RESPONSE))) {
//       uploadDebugLogs("NFC device to data send check:ok");
//       // 修改部分
//       const int chunkSize = 2048;
//       int dataLen = preSendData.length();
//       if (dataLen > chunkSize) {
//         for (int i = 0; i < dataLen; i += chunkSize) {
//           uploadDebugLogs("分包发送,当钱包:"+String(i)+",数据长度:"+String(dataLen));
//           int len = (i + chunkSize < dataLen) ? chunkSize : dataLen - i;
//           String chunk = preSendData.substring(i, i + len);
//           ExtSerial.print(chunk);
//           delay(100);
//         }
//       } else {
//         ExtSerial.print(preSendData);
//       }
//       return;
//     }else if (checkResponse(BUSY_RESPONSE, sizeof(BUSY_RESPONSE))) {
//       Serial.println("Device busy, retrying...");
//       uploadDebugLogs("NFC Device busy, retrying...");
//       delay(1000);
//       retryCount++;
//     } else {
//       uploadDebugLogs("NFC Device Invalid response");
//       Serial.println("Invalid response");
//       delay(1000);
//       retryCount++;
//     }
//   }
  
//   if (retryCount >= 4) {
//     Serial.println("Max retries exceeded");
//   }
// }


void reconnect()
{
  // Loop until we're reconnected
  while (!client.connected())
  {
    uploadDebugLogs("Attempting MQTT connection to ");
    uploadDebugLogs(mqttServer);

    // Attempt to connect
    char ID[20];
    sprintf(ID, "ESP32Client-%04X", random(0xffff));
    // 设置更长的Keep Alive时间（120秒）
    client.setKeepAlive(120);
    client.setCallback(callback);
    if (client.connect(ID, mqtt_username, mqtt_psd))
    {
      uploadDebugLogs("...connected");

      // Once connected, publish an announcement...
      String data = "Hello from MQTTClient_SSL on " + String(BOARD_NAME);

      client.publish(TOPIC, data.c_str());

      uploadDebugLogs("Published connection message successfully!");
      uploadDebugLogs("Subscribed to: ");
      uploadDebugLogs(subTopic);

      // This is a workaround to address https://github.com/OPEnSLab-OSU/SSLClient/issues/9
      //ethClientSSL.flush();
      // ... and resubscribe
      bool subResult1 = client.subscribe(subTopic);
      // for loopback testing
      // bool subResult2 = client.subscribe(TOPIC);

      uploadDebugLogs("Subscribed to TOPIC: " + String(TOPIC) + " - " + (subResult1 ? "Success" : "Failed"));
      // uploadDebugLogs("Subscribed to subTopic: " + String(subTopic) + " - " + (subResult2 ? "Success" : "Failed"));
      // This is a workaround to address https://github.com/OPEnSLab-OSU/SSLClient/issues/9
      //ethClientSSL.flush();
      uploadDebugLogs("重连机制检测:mqtt已连接");
    } else {
      uploadDebugLogs("...failed, rc=");
      //uploadDebugLogs(client.state());
      uploadDebugLogs(" try again in 5 seconds");

      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
